import { snippets } from "@/lib/generated/snippets";
import { Snippet } from "@/components/code";
import { Callout, Card, Cards, Steps, Tabs } from "nextra/components";
import UniversalTabs from "@/components/UniversalTabs";

# Scheduled Runs

> This example assumes we have a [task](./your-first-task.mdx) registered on a running [worker](./workers.mdx).

Scheduled runs allow you to trigger a task at a specific time in the future. Some example use cases of scheduling runs might include:

- Sending a reminder email at a specific time after a user took an action.
- Running a one-time maintenance task at a predetermined time as determined by your application. For instance, you might want to run a database vacuum during a maintenance window any time a task matches a certain criteria.
- Allowing a customer to decide when they want your application to perform a specific task. For instance, if your application is a simple alarm app that sends a customer a notification at a time that they specify, you might create a scheduled run for each alarm that the customer sets.

Hatchet supports scheduled runs to run on a schedule defined in a few different ways:

- [Programmatically](./scheduled-runs.mdx#programmatically-creating-scheduled-runs): Use the Hatchet SDKs to dynamically set the schedule of a task.
- [Hatchet Dashboard](./scheduled-runs.mdx#managing-scheduled-runs-in-the-hatchet-dashboard): Manually create scheduled runs from the Hatchet Dashboard.

<Callout type="warning">
  The scheduled time is when Hatchet **enqueues** the task, not when the run
  starts. Scheduling constraints like concurrency limits, rate limits, and retry
  policies can affect run start times.
</Callout>

## Programmatically Creating Scheduled Runs

### Create a Scheduled Run

You can create dynamic scheduled runs programmatically via the API to run tasks at a specific time in the future.

Here's an example of creating a scheduled run to trigger a task tomorrow at noon:

<UniversalTabs items={["Python", "Typescript", "Go"]}>
  <Tabs.Tab title="Python">

<Snippet src={snippets.python.simple.schedule.schedule_a_task} />

</Tabs.Tab>
<Tabs.Tab title="Typescript">
<Snippet src={snippets.typescript.simple.schedule.create_a_scheduled_run} />
</Tabs.Tab>
<Tabs.Tab title="Go">
<Snippet src={snippets.go.scheduled.main.create} />
</Tabs.Tab>
</UniversalTabs>

In this example you can have different scheduled times for different customers, or dynamically set the scheduled time based on some other business logic.

When creating a scheduled run via the API, you will receive a scheduled run object with a metadata property containing the id of the scheduled run. This id can be used to reference the scheduled run when deleting the scheduled run and is often stored in a database or other persistence layer.

<Callout type="info">
  Note: Be mindful of the time zone of the scheduled run. Scheduled runs are
  **always** stored and returned in UTC.
</Callout>

### Deleting a Scheduled Run

You can delete a scheduled run by calling the `delete` method on the scheduled run object.

<UniversalTabs items={["Python", "Typescript", "Go"]}>
  <Tabs.Tab title="Python">
    <Snippet src={snippets.python.scheduled.programatic_sync.delete} />
  </Tabs.Tab>
  <Tabs.Tab title="Typescript">
    <Snippet src={snippets.typescript.simple.schedule.delete_a_scheduled_run} />
  </Tabs.Tab>
  <Tabs.Tab title="Go">
    <Snippet src={snippets.go.scheduled.main.delete} />
  </Tabs.Tab>
</UniversalTabs>

### Listing Scheduled Runs

You can list all scheduled runs for a task by calling the `list` method on the scheduled run object.

<UniversalTabs items={["Python", "Typescript", "Go"]}>
  <Tabs.Tab title="Python">
    <Snippet src={snippets.python.scheduled.programatic_sync.list} />
  </Tabs.Tab>
  <Tabs.Tab title="Typescript">
    <Snippet src={snippets.typescript.simple.schedule.list_scheduled_runs} />
  </Tabs.Tab>
  <Tabs.Tab title="Go">
    <Snippet src={snippets.go.scheduled.main.list} />
  </Tabs.Tab>
</UniversalTabs>

## Managing Scheduled Runs in the Hatchet Dashboard

In the Hatchet Dashboard, you can view and manage scheduled runs for your tasks.

Navigate to "Triggers" > "Scheduled Runs" in the left sidebar and click "Create Scheduled Run" at the top right.

You can specify run parameters such as Input, Additional Metadata, and the Scheduled Time.

![Create Scheduled Run](../../public/schedule-dash.gif)

## Scheduled Run Considerations

When using scheduled runs, there are a few considerations to keep in mind:

1. **Time Zone**: Scheduled runs are stored and returned in UTC. Make sure to consider the time zone when defining your scheduled time.

2. **Execution Time**: The actual execution time of a scheduled run may vary slightly from the scheduled time. Hatchet makes a best-effort attempt to enqueue the task as close to the scheduled time as possible, but there may be slight delays due to system load or other factors.

3. **Missed Schedules**: If a scheduled task is missed (e.g., due to system downtime), Hatchet will not automatically run the missed instances when the service comes back online.

4. **Overlapping Schedules**: If a task is still running when a second scheduled run is scheduled to start, Hatchet will start a new instance of the task or respect [concurrency](./concurrency.mdx) policy.
